package dcl.software.filesync.client;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.common.ImageMetadata.Item;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.constants.ExifTagConstants;
import org.apache.sanselan.formats.tiff.constants.GPSTagConstants;
import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.formats.tiff.constants.TiffTagConstants;

public class FileAnalyzer {
	public static Map<String, String> getMetadataMap(File file) {

		// get all metadata stored in EXIF format (ie. from JPEG or TIFF).
		IImageMetadata metadata = null;
		try
		{
		metadata = Sanselan.getMetadata(file);
		}catch (Exception e)
		{
			System.err.println("Failed to get properties for: "+file.getAbsolutePath());
			e.printStackTrace();
		}
		Map<String, String> properties = new HashMap<>();
		// System.out.println(metadata);

		if (metadata instanceof JpegImageMetadata) {
			final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;

			// Jpeg EXIF metadata is stored in a TIFF-based directory structure
			// and is identified with TIFF tags.
			// Here we look for the "x resolution" tag, but
			// we could just as easily search for any other tag.
			//
			// see the TiffConstants file for a list of TIFF tags.

			System.out.println("file: " + file.getPath());

			// print out various interesting EXIF tags.
			printTagValue(jpegMetadata, TiffTagConstants.TIFF_TAG_XRESOLUTION, properties);
			printTagValue(jpegMetadata, TiffTagConstants.TIFF_TAG_DATE_TIME, properties);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, properties);
			// printTagValue(jpegMetadata,
			// ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_ISO, properties);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_SHUTTER_SPEED_VALUE, properties);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_APERTURE_VALUE, properties);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_BRIGHTNESS_VALUE, properties);
			printTagValue(jpegMetadata, GPSTagConstants.GPS_TAG_GPS_LATITUDE_REF, properties);
			printTagValue(jpegMetadata, GPSTagConstants.GPS_TAG_GPS_LATITUDE, properties);
			printTagValue(jpegMetadata, GPSTagConstants.GPS_TAG_GPS_LONGITUDE_REF, properties);
			printTagValue(jpegMetadata, GPSTagConstants.GPS_TAG_GPS_LONGITUDE, properties);

			// simple interface to GPS data

/*			final TiffImageMetadata exifMetadata = jpegMetadata.getExif();
			if (null != exifMetadata) {
				final TiffImageMetadata.GPSInfo gpsInfo = exifMetadata.getGPS();
				if (null != gpsInfo) {
					final String gpsDescription = gpsInfo.toString();
					final double longitude = gpsInfo.getLongitudeAsDegreesEast();
					final double latitude = gpsInfo.getLatitudeAsDegreesNorth();

					System.out.println("    " + "GPS Description: " + gpsDescription);
					System.out.println("    " + "GPS Longitude (Degrees East): " + longitude);
					System.out.println("    " + "GPS Latitude (Degrees North): " + latitude);
				}
			}

			// more specific example of how to manually access GPS values
			final TiffField gpsLatitudeRefField = jpegMetadata.findEXIFValue(GPSTagConstants.GPS_TAG_GPS_LATITUDE_REF);
			final TiffField gpsLatitudeField = jpegMetadata.findEXIFValue(GPSTagConstants.GPS_TAG_GPS_LATITUDE);
			final TiffField gpsLongitudeRefField = jpegMetadata.findEXIFValue(GPSTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
			final TiffField gpsLongitudeField = jpegMetadata.findEXIFValue(GPSTagConstants.GPS_TAG_GPS_LONGITUDE);
			if (gpsLatitudeRefField != null && gpsLatitudeField != null && gpsLongitudeRefField != null && gpsLongitudeField != null) {
				// all of these values are strings.
				final String gpsLatitudeRef = (String) gpsLatitudeRefField.getValue();
				final RationalNumber gpsLatitude[] = (RationalNumber[]) (gpsLatitudeField.getValue());
				final String gpsLongitudeRef = (String) gpsLongitudeRefField.getValue();
				final RationalNumber gpsLongitude[] = (RationalNumber[]) gpsLongitudeField.getValue();

				final RationalNumber gpsLatitudeDegrees = gpsLatitude[0];
				final RationalNumber gpsLatitudeMinutes = gpsLatitude[1];
				final RationalNumber gpsLatitudeSeconds = gpsLatitude[2];

				final RationalNumber gpsLongitudeDegrees = gpsLongitude[0];
				final RationalNumber gpsLongitudeMinutes = gpsLongitude[1];
				final RationalNumber gpsLongitudeSeconds = gpsLongitude[2];

				// This will format the gps info like so: //
				// gpsLatitude: 8 degrees, 40 minutes, 42.2 seconds S
				// gpsLongitude: 115 degrees, 26 minutes, 21.8 seconds E

				System.out.println("    " + "GPS Latitude: " + gpsLatitudeDegrees.toDisplayString() + " degrees, "
				        + gpsLatitudeMinutes.toDisplayString() + " minutes, " + gpsLatitudeSeconds.toDisplayString() + " seconds " + gpsLatitudeRef);
				System.out.println("    " + "GPS Longitude: " + gpsLongitudeDegrees.toDisplayString() + " degrees, "
				        + gpsLongitudeMinutes.toDisplayString() + " minutes, " + gpsLongitudeSeconds.toDisplayString() + " seconds "
				        + gpsLongitudeRef);

			}*/

			final List<Item> items = jpegMetadata.getItems();
			for (int i = 0; i < items.size(); i++) {
				final Item item = items.get(i);
				properties.put(item.getKeyword(), item.getText());
			}
		}
		analyze(file, properties);
		return properties;
	}

	private static void printTagValue(final JpegImageMetadata jpegMetadata, final TagInfo tagInfo, Map<String, String> properties) {
		final TiffField field = jpegMetadata.findEXIFValue(tagInfo);
		if(field!=null)
		properties.put(tagInfo.name,field.getValueDescription());
	}

	private static void analyze(File file, Map<String, String> properties) {
		if (file.exists()) {
			Path path = Paths.get(file.getAbsolutePath());
			BasicFileAttributes attr = null;
			try {
				attr = Files.readAttributes(path, BasicFileAttributes.class);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			properties.put("Last Modified Time",attr.lastModifiedTime().toString());
			properties.put("Creation Time",attr.creationTime().toString());
			properties.put("Last Access Time",attr.lastAccessTime().toString());
			properties.put("Size","" + attr.size());
/*			try {
				FileReader fr = new FileReader(file);
				int read = 0;
				while ((read = fr.read()) != -1 && false) {
					prev = size;
					size += read;
					if (prev > size)
						overlap++;
				}
				fr.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
			}*/
		}
	}
}